﻿Imports System.IO
Imports System.Drawing.Imaging

Public Class Studio

   Public Shared Albums As New Table(Of Album)("m:\", "albums")
   Public Shared Files As New Table(Of File)("m:\", "files")

	Public Shared Sub Open()
		Files.Open()
		Albums.Open()
		If Files.IsEmpty Then InitializePhotoDB()
		If Not My.Computer.FileSystem.DirectoryExists(ThumbFolder) Then My.Computer.FileSystem.CreateDirectory(ThumbFolder)
		If Not My.Computer.FileSystem.DirectoryExists(SmallFolder) Then My.Computer.FileSystem.CreateDirectory(SmallFolder)
      Images.StartProcessing()
	End Sub

   Shared Sub InitializePhotoDB()
      ExploreFolder(MainFolder)
      Files.Save()
   End Sub

   Shared Sub ExploreFolder(ByVal Folder As String)
      For Each Extension In "jpg.mov.avi".Split(".")
         For Each File In My.Computer.FileSystem.GetFiles(Folder, FileIO.SearchOption.SearchTopLevelOnly, "*." & Extension)
            'Files.AddNew("name,date", My.Computer.FileSystem.GetName(File), "")
         Next
      Next
      For Each SubFolder In My.Computer.FileSystem.GetDirectories(Folder, FileIO.SearchOption.SearchTopLevelOnly)
         ExploreFolder(SubFolder)
      Next
   End Sub

	Shared Sub Invalidate(ByVal File As String)
		MainForm.Redraw(File)
		'Dim Items = FrmMain.List.Find(File)
		'If Items.Any Then FrmMain.List.Invalidate(Items.First.Bounds)
		'If FrmMain.Picture.File = File Then FrmMain.Picture.Invalidate()
	End Sub

End Class

Public Class Table(Of x) : Inherits List(Of x)

   Dim RemoteFolder As String = ""
   Dim FileName As String
   Dim LocalFolder = My.Computer.FileSystem.SpecialDirectories.Temp & "\"
   Dim SortedList As New SortedList(Of String, x)

   Sub New(ByVal RemoteFolder As String, ByVal FileName As String)
      Me.RemoteFolder = RemoteFolder
      Me.FileName = FileName
   End Sub

   Dim RemoteVersion As Integer = 0
   Dim LocalVersion As Integer = 0

   Sub Open()
      RemoteVersion = GetVersion(RemoteFolder, FileName)
      LocalVersion = GetVersion(LocalFolder, FileName)
      If LocalVersion < RemoteVersion Then
         My.Computer.FileSystem.CopyFile(RemoteFolder & FileName & "." & RemoteVersion, LocalFolder & FileName & "." & RemoteVersion)
         LocalVersion = RemoteVersion
      End If
      If LocalVersion > 0 Then Import(LocalFolder & FileName & "." & LocalVersion)
   End Sub

   Function GetVersion(ByVal Folder As String, ByVal File As String) As Integer
      Dim Files = My.Computer.FileSystem.GetFiles(Folder, FileIO.SearchOption.SearchTopLevelOnly, File & ".*")
      If Files.Count = 0 Then Return 0
      Return (From f In Files Select Val(Mid(f, InStrRev(f, ".") + 1))).Max
   End Function

   ReadOnly Property IsEmpty As Boolean
      Get
         Return Count = 0
      End Get
   End Property

   Overloads Sub Save()
      LocalVersion += 1
      Export(LocalFolder & FileName & "." & LocalVersion)
      If LocalVersion > 10 Then
         For i = 1 To 2
            Dim ObsoleteFile = Choose(i, LocalFolder, RemoteFolder) & FileName & "." & (LocalVersion - 10)
            If My.Computer.FileSystem.FileExists(ObsoleteFile) Then My.Computer.FileSystem.DeleteFile(ObsoleteFile)
         Next
      End If
      My.Computer.FileSystem.CopyFile(LocalFolder & FileName & "." & LocalVersion, RemoteFolder & FileName & "." & LocalVersion)
      'If Not AsyncSave.IsBusy Then AsyncSave.RunWorkerAsync()
   End Sub

   Dim WithEvents AsyncSave As New System.ComponentModel.BackgroundWorker

   Private Sub AsyncSave_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles AsyncSave.DoWork
      My.Computer.FileSystem.CopyFile(LocalFolder & FileName & "." & LocalVersion, RemoteFolder & FileName & "." & LocalVersion)
   End Sub

   Private Sub AsyncSave_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles AsyncSave.RunWorkerCompleted
      RemoteVersion = LocalVersion
   End Sub

   Shadows Sub Add(ByVal Key As String, ByVal Item As x)
      MyBase.Add(Item)
      SortedList.Add(Key, Item)
   End Sub

   Sub Export(ByVal File As String)
      Dim Builder As New System.Text.StringBuilder
      Dim Members = GetType(x).GetProperties
      For Each Item As x In Me
         For Each Member In Members
            Builder.Append(Member.Name & "=" & Trim(CallByName(Item, Member.Name, CallType.Get)) & vbTab)
         Next
         Builder.Append(vbCrLf)
      Next
      My.Computer.FileSystem.WriteAllText(File, Builder.ToString, False, System.Text.Encoding.Default)
   End Sub

   Sub Delete(ByVal Key As String)
      Dim Item = Me(Key)
      SortedList.Remove(Key)
      Remove(Item)
   End Sub

   Sub Import(ByVal File As String)
      Clear()
      Dim Members = GetType(x).GetProperties
      For Each Line In Split(My.Computer.FileSystem.ReadAllText(File, System.Text.Encoding.Default), vbCrLf)
         If Line <> "" Then
            Dim Record = Activator.CreateInstance(Of x)()
            Dim Key As String = ""
            For Each Item As String In Line.Split(vbTab)
               If Item <> "" Then
                  Dim Pos = InStr(Item, "=")
                  Dim Field = Mid(Item, 1, Pos - 1)
                  If (From m In Members Where LCase(m.Name) = LCase(Field)).Any Then
                     If Key = "" Then Key = Mid(Item, Pos + 1)
                     CallByName(Record, Field, CallType.Set, Mid(Item, Pos + 1))
                  End If
               End If
            Next
            Add(Key, Record)
         End If
      Next
   End Sub

   Default Shadows Property Item(ByVal Key As String) As x
      Get
         Return SortedList(Key)
      End Get
      Set(ByVal Value As x)
         SortedList(Key) = Value
      End Set
   End Property

   Shadows Function Contains(ByVal Key As String) As Boolean
      Return SortedList.ContainsKey(Key)
   End Function

End Class

Public Class Record

   Public Key As String

End Class

Public Class File : Inherits Record

   Public Property Name As String
   Public Property Exif As String
   Public Property Datetime As String
   Public Property Make As String
   Public Property Model As String
   Public Property Width As String
   Public Property Height As String

   Friend Status As String

   Function LocalName(ByVal i As Integer) As String
      Return My.Computer.FileSystem.SpecialDirectories.Temp & "\" & Name.Replace("\", ".").Replace(":", ".") & "." & Choose(i + 1, "thumb", "small", "big")
   End Function

   Function CentralName(ByVal i As Integer) As String
      If i = 0 Then Return ThumbFolder & Name.Replace("\", ".").Replace(":", ".") & ".thumb"
      If i = 1 Then Return SmallFolder & Name.Replace("\", ".").Replace(":", ".") & ".small"
      Return My.Computer.FileSystem.GetFiles(MainFolder, FileIO.SearchOption.SearchAllSubDirectories, Name).First
   End Function

End Class